#include "TListaMensajes.h"


int LM_Crear(TListaMensajes* lista) {
	lista->tam_dato = sizeof(TElemListaMensajes);
	lista->lista_simple = (TListaSimple*) malloc(sizeof(TListaSimple));
	#ifdef __DEBUG__
	printf("LM_Crear: Entra.\n");
	#endif
	if (!(lista->lista_simple)) {
		return TLM_ERR_MEMORIA;
	}

	LS_Crear(lista->lista_simple, lista->tam_dato);
	return TLM_OK;
}

int LM_Destruir(TListaMensajes* lista) {
	/* destruir_nodos(lista->lista_simple); HAY QUE DESTRUIR LOS NODOS IGUALMENTE USANDO PRIMITIVAS */
	TElemListaMensajes* nodo = malloc(sizeof(TElemListaMensajes));

	        LS_MoverCorriente(lista->lista_simple, LS_PRIMERO);
	        while (!LS_Vacia(*(lista->lista_simple))) {
	                LS_ElemCorriente(*(lista->lista_simple), nodo);
	                TNLM_Destruir(nodo);
	                LS_BorrarCorriente(lista->lista_simple);
	        }

	        LS_Vaciar(lista->lista_simple);
	        free(nodo);
	lista->tam_dato = -1;
	free(lista->lista_simple);
	return TLM_OK;
}


int LM_InsertarMensaje(TListaMensajes* lista, TMensaje* mensaje) {
	TTipoMensaje prioritario;
	TPuerto puerto_mensaje;

	prioritario = Mensaje_ObtenerPrioridad(mensaje);
	puerto_mensaje = Mensaje_ObtenerPuerto(mensaje);

	if (LS_Vacia(*(lista->lista_simple))) {
			TElemListaMensajes* elemento_lm;

			elemento_lm = (TElemListaMensajes*) malloc(sizeof(TElemListaMensajes));
			TNLM_Crear(elemento_lm, puerto_mensaje, sizeof(TMensaje));


			if (prioritario == PRIORITARIO) {
				TNLM_InsertarMensajePrioritario(elemento_lm, mensaje);
			}
			else if (prioritario == NO_PRIORITARIO) {
				TNLM_InsertarMensajeNoPrioritario(elemento_lm, mensaje);
			}

			LS_Insertar(lista->lista_simple, LS_SIGUIENTE, elemento_lm);
			free(elemento_lm);

	}
	else {
		/* Busco el TElemLM que corresponde al puerto*/
		int encontrado = 0;
		TMovimiento movimiento;
		TPuerto puerto_elemento;
		TElemListaMensajes corriente;

		movimiento = LS_PRIMERO;

		while (LS_MoverCorriente(lista->lista_simple, movimiento)) {
			movimiento = LS_SIGUIENTE;
			LS_ElemCorriente(*(lista->lista_simple), &corriente);
			puerto_elemento = TNLM_ObtenerPuerto(&corriente);
			if ((int)puerto_elemento == (int)puerto_mensaje) {
				encontrado = 1;
				if (prioritario == PRIORITARIO) {
					TNLM_InsertarMensajePrioritario(&corriente, mensaje);
				}
				else if (prioritario == NO_PRIORITARIO) {
					TNLM_InsertarMensajeNoPrioritario(&corriente, mensaje);
				}
				LS_ModifCorriente(lista->lista_simple, &corriente);
				break;
			}


		}
		/* si el puerto no existe, lo creo */
		if (!encontrado) {
			TElemListaMensajes* elemento_lm;

			elemento_lm = (TElemListaMensajes*) malloc(sizeof(TElemListaMensajes));
			TNLM_Crear(elemento_lm, puerto_mensaje, sizeof(TMensaje));


			if (prioritario == PRIORITARIO) {
				TNLM_InsertarMensajePrioritario(elemento_lm, mensaje);
			}
			else if (prioritario == NO_PRIORITARIO) {
				TNLM_InsertarMensajeNoPrioritario(elemento_lm, mensaje);
			}

			LS_Insertar(lista->lista_simple, LS_SIGUIENTE, elemento_lm);
			free(elemento_lm);
		}
	}
	return TLM_OK;
}


int LM_ObtenerMensaje(TListaMensajes* lista, TPuerto puerto, TTipoMensaje es_prioritario, TMensaje* mensaje_out) {
	TElemListaMensajes* elem;
	TPuerto p;
	int codigo_error;

	elem = (TElemListaMensajes*) malloc(sizeof(TElemListaMensajes));

	if (!elem) {
		return TLM_ERR_MEMORIA;
	}

	if (LS_Vacia(*(lista->lista_simple))) {
		#ifdef __DEBUG__
		printf("LM_ObtenerMensaje:\n Lista Vacia\n");
		#endif
		free(elem);
		return TLM_ERR_SINMENSAJES;
	}

	LS_MoverCorriente(lista->lista_simple, LS_PRIMERO);
	LS_ElemCorriente(*(lista->lista_simple), elem);
	#ifdef __DEBUG__
	printf("puerto del elemento = %d", TNLM_ObtenerPuerto(elem));
	#endif
	p = TNLM_ObtenerPuerto(elem);
	while (p < puerto) {
		LS_MoverCorriente(lista->lista_simple, LS_SIGUIENTE);
		LS_ElemCorriente(*(lista->lista_simple), elem);
		p = TNLM_ObtenerPuerto(elem);
	}

	if (TNLM_ObtenerPuerto(elem) > puerto) {
		#ifdef __DEBUG__
		printf("LM_ObtenerMensaje:\n No existe puerto\n");
		#endif
		free(elem);
		return TLM_ERR_SINMENSAJES;
	}
	else {
		#ifdef __DEBUG__
		printf("LM_ObtenerMensaje:\n Puerto encontrado\n");
		#endif
		if (es_prioritario) {
			codigo_error = TNLM_ObtenerMensajePrioritario(elem, mensaje_out);
			if (TNLM_ObtenerPuerto(elem) == -1){
			  LS_BorrarCorriente(lista->lista_simple);
			  free(elem);
			  return codigo_error;
		  }
		  free(elem);
		  return codigo_error;
		}
		else {
			codigo_error = TNLM_ObtenerMensajeNoPrioritario(elem, mensaje_out);
			if (TNLM_ObtenerPuerto(elem) == -1) {
				LS_BorrarCorriente(lista->lista_simple);
				free(elem);
				return TLM_OK;
			}

			free(elem);
			return codigo_error;
		}
	}
}
